#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import os
from abc import ABCMeta, abstractmethod

from common.common import output_result_file
from common.common_models import ActionResult, SubJobDetails, RepositoryPath, ScanRepositories
from common.const import SubJobStatusEnum, RepositoryDataTypeEnum, BackupTypeEnum
from common.number_const import NumberConst
from db2.comm.backup_param_parse import ParameterBackupParse
from db2.comm.util.common_util import Db2CommonUtil, LOGGER


class Db2BackupBase(metaclass=ABCMeta):
    """Db2备份任务执行基类
    """
    def __init__(self, task_name, pid, job_id, sub_job_id, param_dict):
        self.task_name = task_name
        self.pid = pid
        Db2CommonUtil.check_injection(str(job_id))
        self._parameter_backup = ParameterBackupParse(pid, job_id, sub_job_id, param_dict)
        self.job_id = job_id
        self.sub_job_id = sub_job_id
        self.param_dict = param_dict
        self.sub_job_detail = SubJobDetails(
            taskId=self.job_id, subTaskId=self.sub_job_id, progress=NumberConst.ONE,
            logDetail=list(), taskStatus=SubJobStatusEnum.RUNNING.value)

    @abstractmethod
    def allow_backup_in_local_node(self):
        """是否允许本地运行"""
        pass

    @abstractmethod
    def check_backup_job_type(self):
        """检查备份任务类型"""
        pass

    @abstractmethod
    def query_job_permission(self):
        """查询应用权限信息"""
        pass

    @abstractmethod
    def exec_backup_pre_job(self):
        """备份前置"""
        pass

    @abstractmethod
    def exec_backup(self):
        """备份任务"""
        pass

    def query_scan_repositories(self):
        # E6000适配
        LOGGER.info(f"query_scan_repositories, pid: {self.pid}, job_id: {self.job_id}, sub_id: {self.sub_job_id}.")
        param_data_path = self._parameter_backup.get_repositories_path(RepositoryDataTypeEnum.DATA_REPOSITORY)
        param_log_path = self._parameter_backup.get_repositories_path(RepositoryDataTypeEnum.LOG_REPOSITORY)
        param_meta_path = self._parameter_backup.get_repositories_path(RepositoryDataTypeEnum.META_REPOSITORY)
        if self._parameter_backup.get_backup_type() == BackupTypeEnum.LOG_BACKUP:
            LOGGER.info(f"query_scan_repositories for log bkp, job_id: {self.job_id}, sub_id: {self.sub_job_id}.")
            # log仓的meta区 /Database_{resource_id}_LogRepository_su{num}/{ip}/meta/{job_id}
            meta_copy_path = os.path.join(os.path.dirname(param_log_path), self.job_id)
            # log仓的data区 /Database_{resource_id}_LogRepository_su{num}/{ip}/{job_id}
            data_path = param_log_path
            # /Database_{resource_id}_LogRepository_su{num}/{ip}
            save_path = os.path.dirname(param_log_path)
        else:
            LOGGER.info(f"query_scan_repositories for data bkp.")

            # meta/Database_{resource_id}_InnerDirectory_su{num}/source_policy_{job_id}/Context_Global_MD/{ip}
            meta_copy_path = param_meta_path
            # data/Database_{resource_id}_InnerDirectory_su{num}/source_policy_{job_id}/Context/{ip}
            data_path = param_data_path
            # meta/Database_{resource_id}_InnerDirectory_su{num}/source_policy_{job_id}/Context_Global_MD/{ip}
            save_path = param_meta_path

        log_meta_copy_repo = RepositoryPath(repositoryType=RepositoryDataTypeEnum.META_REPOSITORY,
                                            scanPath=meta_copy_path)
        log_data_repo = RepositoryPath(repositoryType=RepositoryDataTypeEnum.DATA_REPOSITORY, scanPath=data_path)
        scan_repos = ScanRepositories(scanRepoList=[log_data_repo, log_meta_copy_repo], savePath=save_path)
        LOGGER.info(f"query_scan_repositories success, req_id: {self.pid}, job_id: {self.job_id}.")
        output_result_file(self.pid, scan_repos.dict(by_alias=True))

    @abstractmethod
    def exec_backup_post_job(self):
        """备份后置"""
        pass

    @abstractmethod
    def query_backup_copy(self):
        """查询副本信息"""
        pass

    @abstractmethod
    def abort_job(self):
        """中止任务"""
        pass

    @abstractmethod
    def report_progress(self):
        """上报进度"""
        pass

    @abstractmethod
    def output_action_result(self, action_ret: ActionResult):
        """输出任务结果到结果文件"""
        Db2CommonUtil.output_action_result(
            self.pid, action_ret.code, body_err=action_ret.body_err, message=action_ret.message,
            err_params=action_ret.body_err_params)
